#include <CppUTest/TestHarness.h>
#include "RateCalculator.hpp"
#include "Customer.hpp"
#include "Site.hpp"

// ##########################################################################
TEST_GROUP(CalculateRatesEmptyCustomer) {
	RateCalculator rateCalculator;
	Customer *customer;

	TEST_SETUP() {
		customer = new Customer();
	}

	TEST_TEARDOWN() {
		delete customer;
	}
	void validateRate(double expectedRate) {
		double actualRate = rateCalculator.calculateRate(*customer);
		CHECK_EQUAL(expectedRate, actualRate);
	}

	void setKwh(int kwh) {
		customer->kwh = kwh;
	}
};

TEST(CalculateRatesEmptyCustomer, blankCustomerHas0Rate) {
	validateRate(0);
}

// ##########################################################################
TEST_GROUP_BASE(CalculateRateForConsumerLifelineTest, CppUTestGroupCalculateRatesEmptyCustomer) {
	TEST_SETUP() {
		CppUTestGroupCalculateRatesEmptyCustomer::setup();
		customer->address = 1;
		customer->type = Customer::consumer;
		customer->rate = Customer::lifeline;
	}
};

TEST(CalculateRateForConsumerLifelineTest, lifeline200Kwh) {
	setKwh(200);
	validateRate(8);
}

TEST(CalculateRateForConsumerLifelineTest, lifeline100Kwh) {
	setKwh(100);
	validateRate(3);
}

TEST(CalculateRateForConsumerLifelineTest, lifeline500KwhSameAsTerritorial) {
	setKwh(500);
	validateRate(30);
}

// ##########################################################################
TEST_GROUP_BASE(CalculateRateForConsumerTerritorialTest, CppUTestGroupCalculateRatesEmptyCustomer) {
	TEST_SETUP() {
		CppUTestGroupCalculateRatesEmptyCustomer::setup();
		customer->type = Customer::consumer;
		customer->rate = Customer::territorial;
		setKwh(500);
	}
};

TEST(CalculateRateForConsumerTerritorialTest, territorial500KwhWithAddressCategory1) {
	customer->address = 1;
	validateRate(30);
}

TEST(CalculateRateForConsumerTerritorialTest, territorial500KwhAddressCategory3) {
	customer->address = 3;
	validateRate(32.5);
}

// ##########################################################################
TEST_GROUP_BASE(CalculateRateForIndustrialCustomerTest, CppUTestGroupCalculateRatesEmptyCustomer) {
	TEST_SETUP() {
		CppUTestGroupCalculateRatesEmptyCustomer::setup();
		customer->type = Customer::industrial;
	}

	void addSite(int kwh) {
		Site *site = new Site();
		site->kwh = kwh;
		customer->sites.push_back(site);
	}
};

TEST(CalculateRateForIndustrialCustomerTest, industrialWith0Sites0) {
	validateRate(0);
}

TEST(CalculateRateForIndustrialCustomerTest, industrialWith1Site100Kwh) {
	addSite(100);
	validateRate(95);
}


// ##########################################################################
TEST_GROUP_BASE(CalculateRateForIndustrialCustomerWithThreeSitesTest, CppUTestGroupCalculateRateForIndustrialCustomerTest) {
	TEST_SETUP() {
		CppUTestGroupCalculateRateForIndustrialCustomerTest::setup();
		addSite(300);
		addSite(600);
		addSite(9700);
	}
};

TEST(CalculateRateForIndustrialCustomerWithThreeSitesTest, industrialWith3SitesVariableKwh) {
	validateRate(10070);
}

TEST(CalculateRateForIndustrialCustomerWithThreeSitesTest, industrialInterruptable) {
	customer->industrialRate = Customer::interruptable;
	validateRate(8480);
}

TEST(CalculateRateForIndustrialCustomerWithThreeSitesTest, industrialOneHourNotice) {
	customer->industrialRate = Customer::oneHourNotice;
	validateRate(9540);
}

TEST(CalculateRateForIndustrialCustomerWithThreeSitesTest, industrialDefault) {
	customer->industrialRate = Customer::UNDEFINED;
	validateRate(10070);
}
